home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 40 / Amiga Format CD40 (1999-05-11)(Future Publishing)(GB)(Track 1 of 3)[!][issue 1999-06].iso / -seriously_amiga- / misc / lunar / original / lunar.c < prev    next >
C/C++ Source or Header  |  1999-03-29  |  23KB  |  838 lines

  1. char version[] = "Lunar Version 2.0 (June 20, 1991)";
  2.  
  3. /*----------------------------------------------------------------------------
  4.  
  5.  
  6.           Lunar 2.0: A Calendar Conversion Program
  7.                 for
  8.     Gregorian Solar Calendar and Chinese Lunar Calendar
  9.     ---------------------------------------------------
  10.  
  11.     By Fung F. Lee and Ricky Yeung
  12.  
  13.     Copyright (C) 1988,1989,1991  Fung F. Lee and Ricky Yeung
  14.  
  15.     All rights reserved.
  16.     Permission to copy and distribute verbatim copies of this
  17.     document for non-commercial purposes is granted, but changing
  18.     it is not allowed.
  19.     There is absolutely no warranty for this program.
  20.  
  21.     Please send your comments and suggestions to the authors:
  22.     Fung F. Lee    lee@milo.stanford.edu
  23.     Ricky Yeung    yeung@decwrl.dec.com or yeung@atd.dec.com
  24.     
  25.     The special "bitmap" file "lunar.bitmap" was contributed
  26.     by Weimin Liu (weimin@alpha.ece.jhu.edu).
  27.  
  28. ----------------------------------------------------------------------------*/
  29.  
  30. /*
  31. This document contains Highest-bit-set GuoBiao (HGB) code, as adopted by
  32. CCDOS on IBM PC compatibles, ChineseTalk 6.0 (GB version) on Macintosh,
  33. and cxterm on UNIX and X window.  Hence, one may need to transfer this 
  34. document as a **binary** file.
  35.  
  36. References:
  37. 1. "Zhong1guo2 yin1yang2 ri4yue4 dui4zhao4 wan4nian2li4" by Lin2 Qi3yuan2.
  38.    ¡¶ÖйúÒõÑôÈÕÔ¶ÔÕÕÍòÄêÀú¡·£®ÁÖ
  39. 2. "Ming4li3 ge2xin1 zi3ping2 cui4yan2" by Xu2 Le4wu2.
  40.    ¡¶ÃüÀí¸ïÐÂ×Óƽ´âÑÔ¡·£®Ðì
  41.  
  42. */ 
  43.  
  44.  
  45. #include <stdio.h>
  46. #include <string.h>
  47.  
  48. /* "Bitmap" constants */
  49. #define    BMRow    7    /* number of rows for each bitmap */
  50. #define    BMCol    11    /* number of columns for each bitmap */
  51. #define    NBM    26    /* number of bitmaps */
  52. #define NianBM  0
  53. #define YueBM   1
  54. #define RiBM    2
  55. #define ShiBM   3
  56. #define    GanBM    4
  57. #define    ZhiBM    14
  58.  
  59. #define Cyear    1900    /* Note that LC1900.1.1 is SC1900.1.31 */
  60. #define Nyear    101    /* number of years covered by the table */
  61. #define Nmonth  13    /* maximum number of months in a lunar year */
  62.  
  63. typedef struct {
  64. int year, month, day, hour, weekday;
  65. int leap;    /* the lunar month is a leap month */
  66. } Date;
  67.  
  68. static Date SolarFirstDate = {
  69.     /* Wednesday, 12 a.m., 31 January, 1900 */
  70.     1900, 1, 31, 0, 3, 0
  71.     };
  72.  
  73. static Date LunarFirstDate = {
  74.     /* Wednesday, 12 a.m., First day, First month, 1900 */
  75.     1900, 1, 1, 0, 3, 0
  76.     };
  77.  
  78. static Date GanFirstDate = {
  79.     /* geng1-nian2 wu4-yue4 jia3-ri4 jia3-shi2 */
  80.        6,          4,       0,       0,           3, 0
  81.     };
  82.  
  83. static Date ZhiFirstDate = {
  84.     /* zi3-nian2 yin2-yue4 chen2-ri4 zi3-shi2 */
  85.        0,        2,        4,        0,           3, 0
  86.     };
  87.  
  88. static int daysInSolarMonth[13] = {
  89.     0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  90.  
  91. static int moon[2] = {29,30}; /* a short (long) lunar month has 29 (30) days */
  92.  
  93. static long yearInfo[Nyear] = {
  94.     /* encoding:
  95.         b bbbbbbbbbbbb bbbb
  96.        bit#        1 111111000000 0000
  97.             6 543210987654 3210
  98.             . ............ ....
  99.        month#      000000000111
  100.             M 123456789012   L
  101.                 
  102.     b_j = 1 for long month, b_j = 0 for short month
  103.     L is the leap month of the year if 1<=L<=12; NO leap month if L = 0.
  104.     The leap month (if exists) is long one iff M = 1.
  105.     */
  106.                         0x04bd8,    /* 1900 */
  107.     0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950,    /* 1905 */
  108.     0x16554, 0x056a0, 0x09ad0, 0x055d2, 0x04ae0,    /* 1910 */
  109.     0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540,    /* 1915 */
  110.     0x0d6a0, 0x0ada2, 0x095b0, 0x14977, 0x04970,    /* 1920 */
  111.     0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54,    /* 1925 */
  112.     0x02b60, 0x09570, 0x052f2, 0x04970, 0x06566,    /* 1930 */
  113.     0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60,    /* 1935 */
  114.     0x186e3, 0x092e0, 0x1c8d7, 0x0c950, 0x0d4a0,    /* 1940 */
  115.     0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0,    /* 1945 */
  116.     0x092d0, 0x0d2b2, 0x0a950, 0x0b557, 0x06ca0,    /* 1950 */
  117.     0x0b550, 0x15355, 0x04da0, 0x0a5d0, 0x14573,    /* 1955 */
  118.     0x052d0, 0x0a9a8, 0x0e950, 0x06aa0, 0x0aea6,    /* 1960 */
  119.     0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260,    /* 1965 */
  120.     0x0f263, 0x0d950, 0x05b57, 0x056a0, 0x096d0,    /* 1970 */
  121.     0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250,    /* 1975 */
  122.     0x0d558, 0x0b540, 0x0b5a0, 0x195a6, 0x095b0,    /* 1980 */
  123.     0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50,    /* 1985 */
  124.     0x06d40, 0x0af46, 0x0ab60, 0x09570, 0x04af5,    /* 1990 */
  125.     0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58,    /* 1995 */
  126.     0x055c0, 0x0ab60, 0x096d5, 0x092e0, 0x0c960        /* 2000 */
  127. };
  128.  
  129. /*
  130.   In "4-column" calculation, a "mingli" (fortune-telling) calculation,
  131.   the beginning of a month is not the first day of the month as in
  132.   the Lunar Calendar; it is instead governed by "jie2" (festival).
  133.   Interestingly, in the Solar calendar, a jie always comes within three
  134.   days after some fixed date. For example, the jie "li4chun1" (beginning
  135.   of spring) always comes within three days after Feburary 4 of the Solar
  136.   Calendar. This is true at least for the years between 1900 and 2000.
  137.   The table may need to be adjusted if exceptions are found when
  138.   the range is extended.
  139.  
  140.   Meaning of array jie:
  141.   For example, the first integer 4 means the beginning of the 1st month
  142.   is no earlier than Feburary 4; the 12th integer 5 means the beginning of
  143.   the 12th month is no earlier than January 5 (of the next Solar year) in
  144.   the Solar Calendar.
  145.  
  146.   Meaning of array fest:
  147.   Each 24 bit number represents the offsets of the 12 jie's of the year
  148.   from the reference days in jie[]. For example, the number corresponding to
  149.   the "Lunar Year" 1991 is 0x154551, and the two least significant bits
  150.   (bit-1, bit-0) are 01. This means that the first day of the 12th month of
  151.   the "Lunar Year" 1991 falls on January 6, 1992, one day after the reference
  152.   date January 5 as in jie[]. (Incidentally, the first day of that lunar month
  153.   is on January 5.)
  154. */
  155.  
  156. short jie[] = {4, 5, 4, 5, 5, 7, 7, 7, 8, 7, 7, 5};
  157.  
  158. long fest[Nyear] = {
  159.                         0x154551,     /* 1900 */
  160. 0x155555, 0x599555, 0x6a9a56, 0x554551, 0x155555,     /* 1905 */
  161. 0x595555, 0x6a9a56, 0x554551, 0x155555, 0x595555,     /* 1910 */
  162. 0x6a9a56, 0x554551, 0x155555, 0x155555, 0x599655,     /* 1915 */
  163. 0x554511, 0x155551, 0x155555, 0x599655, 0x554511,     /* 1920 */
  164. 0x155561, 0x155555, 0x599655, 0x554511, 0x155551,     /* 1925 */
  165. 0x155555, 0x599555, 0x554501, 0x154551, 0x155555,     /* 1930 */
  166. 0x599555, 0x554501, 0x154551, 0x155555, 0x595555,     /* 1935 */
  167. 0x554501, 0x154551, 0x155555, 0x595555, 0x554501,     /* 1940 */
  168. 0x154551, 0x155555, 0x595555, 0x544501, 0x154511,     /* 1945 */
  169. 0x155555, 0x155555, 0x444100, 0x154511, 0x155555,     /* 1950 */
  170. 0x155555, 0x444100, 0x154511, 0x155551, 0x155555,     /* 1955 */
  171. 0x444100, 0x154511, 0x154551, 0x155555, 0x444000,     /* 1960 */
  172. 0x154501, 0x154551, 0x155555, 0x444000, 0x154501,     /* 1965 */
  173. 0x154551, 0x155555, 0x440000, 0x154501, 0x154551,     /* 1970 */
  174. 0x155555, 0x440000, 0x144501, 0x154551, 0x155555,     /* 1975 */
  175. 0x400000, 0x144101, 0x154511, 0x155555, 0x400000,     /* 1980 */
  176. 0x144101, 0x154511, 0x155555, 0x0,    0x44100,     /* 1985 */
  177. 0x154511, 0x154551, 0x0,      0x44000,  0x154511,     /* 1990 */
  178. 0x154551, 0x0,        0x44000,  0x154501, 0x154551,     /* 1995 */
  179. 0x0,      0x40000,  0x154501, 0x154551, 0x0        /* 2000 */
  180. };
  181.  
  182. static    char    *Gan[] = {
  183.     "Jia3",    "Yi3",     "Bing3", "Ding1", "Wu4",
  184.     "Ji3",    "Geng1", "Xin1",  "Ren2",  "Gui3"
  185. };
  186.  
  187. static    char    *Zhi[] = {
  188.     "Zi3",    "Chou3", "Yin2",  "Mao3",  "Chen2", "Si4",
  189.     "Wu3",    "Wei4",     "Shen1", "You3",  "Xu1",   "Hai4"
  190. };
  191.  
  192. static    char   *ShengXiao[] = {
  193.     "Mouse", "Ox", "Tiger", "Rabbit", "Dragon", "Snake",
  194.     "Horse", "Goat", "Monkey", "Rooster", "Dog", "Pig"
  195. };
  196.  
  197. static char *weekday[] = {
  198.     "Sunday", "Monday", "Tuesday", "Wednesday",
  199.     "Thursday", "Friday", "Saturday"
  200. };
  201.  
  202. static    char    *GanGB[] = {
  203.     "¼×", "ÒÒ", "±û", "¶¡", "Îì",
  204.     "¼º", "¸ý", "ÐÁ", "ÈÉ", "¹ï"
  205. };
  206.  
  207. static    char    *ZhiGB[] = {
  208.     "×Ó", "³ó", "Òú", "î", "³½", "ËÈ",
  209.     "Îç", "δ", "Éê", "ÓÏ", "Ðç", "º¥"
  210. };
  211.  
  212. static    char   *ShengXiaoGB[] = {
  213.     "Êó", "Å£", "»¢", "ÍÃ", "Áú", "Éß",
  214.     "Âí", "Ñò", "ºï", "¼¦", "¹·", "Öí"
  215. };
  216.  
  217. static char *weekdayGB[] = {
  218.     "ÈÕ", "Ò»", "¶þ", "Èý",
  219.     "ËÄ", "Îå", "Áù"
  220. };
  221.  
  222.  
  223. Date solar, lunar, gan, zhi, gan2, zhi2, lunar2;
  224.  
  225. int ymonth[Nyear];    /* number of lunar months in the years */
  226. int yday[Nyear];    /* number of lunar days in the years */
  227. int mday[Nmonth+1];    /* number of days in the months of the lunar year */
  228. int jieAlert;        /* if there is uncertainty in JieQi calculation */
  229.  
  230. int    showHZ = 0;            /* output in hanzi */
  231. int    showBM = 0;            /* output in bitmap */
  232. char    BMfile[] = "lunar.bitmap";    /* bit map file */
  233. char    GZBM[NBM][BMRow][BMCol];    /* the bitmap array */
  234. char    *progname;
  235.  
  236. void    Solar2Lunar(), Lunar2Solar();
  237. long    Solar2Day(), Solar2Day1(), Lunar2Day();
  238. void    Day2Lunar(), Day2Solar();
  239. int     make_yday(), make_mday(), GZcycle();
  240. void    CalGZ();
  241. int    GetFest(), JieDate(), JieDate();
  242. void    readBM(), display3();
  243. void    Report(), ReportE(), ReportBM(), ReportGB();
  244. void    usage(), Error();
  245.  
  246.  
  247. void main(argc, argv)
  248. int argc;
  249. char *argv[];
  250. {
  251.     int year, month, day, hour, i, k, option, inverse=0, leap=0;
  252.     int dateInfo[4];
  253.     
  254.     progname = "lunar";
  255.     printf("%s\n\n", version);
  256.  
  257.     for (k=1; k<argc && argv[k][0]=='-'; k++)
  258.     {
  259.     option = argv[k][1];
  260.     switch(option)
  261.     {
  262.         case 'i': inverse = 1; break;
  263.         case 'l': if (inverse) leap=1; else usage(); break;
  264.         case 'h': showHZ = 1; break;
  265.         case 'b': showBM = 1; break;
  266.         default:  usage(); break;
  267.     }
  268.     }
  269.     if (showBM) readBM();
  270.     if (!((argc - k >= 3) && (argc - k <= 4))) usage();
  271.     dateInfo[3] = 0;
  272.     for (i=0; k<argc && i<4; k++, i++)
  273.     {
  274.     if (sscanf(argv[k], "%d", &dateInfo[i]) != 1)
  275.         usage();
  276.     }
  277.     year = dateInfo[0];
  278.     month = dateInfo[1];
  279.     day = dateInfo[2];
  280.     hour = dateInfo[3];
  281.     if (!(year>=Cyear && year<Cyear+Nyear))
  282.     Error("Year out of range.");
  283.     if (!(month>=1 && month<=12))
  284.     Error("Month out of range.");
  285.     if (!(day>=1 && day<=31) || (inverse && day>30))
  286.     Error("Day out of range.");
  287.     if (!(hour>=0 && hour<=23))
  288.     Error("Hour out of range.");
  289.  
  290.     if (!inverse && year==SolarFirstDate.year &&
  291.     CmpDate(month, day, SolarFirstDate.month, SolarFirstDate.day)<0)
  292.     Error("Date out of range.");
  293.  
  294.     if (inverse)
  295.     {
  296.     lunar.year = year;
  297.     lunar.month = month;
  298.     lunar.day = day;
  299.     lunar.hour = hour;
  300.     lunar.leap = leap;
  301.     Lunar2Solar();
  302.     }
  303.     else
  304.     {
  305.     solar.year = year;
  306.     solar.month = month;
  307.     solar.day = day;
  308.     solar.hour = hour;
  309.     Solar2Lunar();
  310.     }
  311.     Report();
  312. }
  313.  
  314. void usage()
  315. {
  316.     printf("Usage:\n\n");
  317.     printf("Solar->Lunar:\t%s [-h] [-b] year month day [hour]\n", progname);
  318.     printf("\t\t(in Solar Calendar, 24 hour clock)\n\n");
  319.     printf("Lunar->Solar:\t%s [-h] [-b] -i [-l] year month day [hour]\n",
  320.        progname);
  321.     printf("\t\t(in Lunar Calendar, 24 hour clock)\n");
  322.     printf("\t\t-l means the month is a leap month (\"run4 yue4\")\n\n");
  323.     printf("\t\t-h means output in hanzi (GB)\n");
  324.     printf("\t\t-b means output in \"bitmap\"\n\n");
  325.     printf("Date range: about %d years from the Solar Date %d.%d.%d\n", Nyear,
  326.        SolarFirstDate.year, SolarFirstDate.month, SolarFirstDate.day);
  327.     exit(1);
  328. }
  329.  
  330.  
  331. void Solar2Lunar()
  332. {
  333.  
  334.     long offset;
  335.     Date *d;
  336.  
  337.     offset = Solar2Day(&solar);
  338.     solar.weekday = (offset + SolarFirstDate.weekday) % 7;
  339.     
  340.     /* A lunar day begins at 11 p.m. */
  341.     if (solar.hour == 23)
  342.     offset++;
  343.  
  344.     Day2Lunar(offset, &lunar);
  345.     lunar.hour = solar.hour;
  346.     CalGZ(offset, &lunar, &gan, &zhi);
  347.  
  348.     jieAlert = JieDate(&solar, &lunar2);
  349.     lunar2.day = lunar.day;
  350.     lunar2.hour = lunar.hour;
  351.     CalGZ(offset, &lunar2, &gan2, &zhi2);
  352. }
  353.  
  354.  
  355. void Lunar2Solar()
  356. {
  357.     long offset;
  358.     int adj;
  359.     Date *d;
  360.  
  361.     /* A solar day begins at 12 a.m. */
  362.     adj = (lunar.hour == 23)? -1 : 0;
  363.     offset = Lunar2Day(&lunar);
  364.     solar.weekday = (offset+ adj + SolarFirstDate.weekday) % 7;
  365.     Day2Solar(offset + adj, &solar);
  366.     solar.hour = lunar.hour;
  367.     CalGZ(offset, &lunar, &gan, &zhi);
  368.  
  369.     jieAlert = JieDate(&solar, &lunar2);
  370.     lunar2.day = lunar.day;
  371.     lunar2.hour = lunar.hour;
  372.     CalGZ(offset, &lunar2, &gan2, &zhi2);
  373. }
  374.  
  375.  
  376. #define    LeapYear(y)    (((y)%4==0) && ((y)%100!=0) || ((y)%400==0))
  377. #define BYEAR        1201
  378. /* BYEAR % 4 == 1  and BYEAR % 400 == 1 for easy calculation of leap years */
  379. /* assert(BYEAR <= SolarFirstDate.year) */
  380.  
  381. long Solar2Day(d)
  382. Date *d;
  383. {
  384.     return (Solar2Day1(d) - Solar2Day1(&SolarFirstDate));
  385. }
  386.  
  387.  
  388. /* Compute the number of days from the Solar date BYEAR.1.1 */
  389. long Solar2Day1(d)
  390. Date *d;
  391. {
  392.     long offset, delta;
  393.     int i;
  394.  
  395.     delta = d->year - BYEAR;
  396.     if (delta<0) Error("Internal error: pick a larger constant for BYEAR.");
  397.     offset = delta * 365 + delta / 4 - delta / 100 + delta / 400;
  398.     for (i=1; i< d->month; i++)
  399.         offset += daysInSolarMonth[i];
  400.     if ((d->month > 2) && LeapYear(d->year))
  401.     offset++;
  402.     offset += d->day - 1;
  403.  
  404.     if ((d->month == 2) && LeapYear(d->year))
  405.     {
  406.     if (d->day > 29) Error("Day out of range.");
  407.     }
  408.     else if (d->day > daysInSolarMonth[d->month]) Error("Day out of range.");
  409.     return offset;
  410. }
  411.  
  412.  
  413. /* Compute offset days of a lunar date from the beginning of the table */
  414. long Lunar2Day(d)
  415. Date *d;
  416. {
  417.     long offset = 0;
  418.     int year, i, m, nYear, leapMonth;
  419.  
  420.     nYear = make_yday();
  421.     year = d->year - LunarFirstDate.year;
  422.     for (i=0; i<year; i++)
  423.     offset += yday[i];
  424.  
  425.     leapMonth = make_mday(year);
  426.     if ((d->leap) && (leapMonth!=d->month))
  427.     {
  428.     printf("%d is not a leap month in year %d.\n", d->month, d->year);
  429.     exit(1);
  430.     }
  431.     for (m=1; m<d->month; m++)
  432.     offset += mday[m];
  433.     if (leapMonth && 
  434.     ((d->month>leapMonth) || (d->leap && (d->month==leapMonth))))
  435.     offset += mday[m++];
  436.     offset += d->day - 1;
  437.  
  438.     if (d->day > mday[m]) Error("Day out of range.");
  439.  
  440.     return offset;
  441. }
  442.  
  443.  
  444. void Day2Lunar(offset, d)
  445. long offset;
  446. Date *d;
  447.  
  448. {
  449.     int i, m, nYear, leapMonth;
  450.     
  451.     nYear = make_yday();
  452.     for (i=0; i<nYear && offset > 0; i++)
  453.     offset -= yday[i];
  454.     if (offset<0)
  455.     offset += yday[--i];
  456.     if (i==Nyear) Error("Year out of range.");
  457.     d->year = i + LunarFirstDate.year;
  458.  
  459.     leapMonth = make_mday(i);
  460.     for (m=1; m<=Nmonth && offset>0; m++)
  461.     offset -= mday[m];
  462.     if (offset<0)
  463.     offset += mday[--m];
  464.  
  465.     d->leap = 0;    /* don't know leap or not yet */
  466.  
  467.     if (leapMonth>0)    /* has leap month */
  468.     {
  469.     /* if preceeding month number is the leap month,
  470.        this month is the actual extra leap month */
  471.     d->leap = (leapMonth == (m - 1));
  472.  
  473.     /* month > leapMonth is off by 1, so adjust it */
  474.     if (m > leapMonth) --m;
  475.     }
  476.  
  477.     d->month = m;
  478.     d->day = offset + 1;
  479. }
  480.  
  481.  
  482. void Day2Solar(offset, d)
  483. long offset;
  484. Date *d;
  485. {
  486.     int    i, m, days;
  487.  
  488.     /* offset is the number of days from SolarFirstDate */
  489.     offset -= Solar2Day(&LunarFirstDate);  /* the argument is negative */
  490.     /* offset is now the number of days from SolarFirstDate.year.1.1 */
  491.  
  492.     for (i=SolarFirstDate.year;
  493.          (i<SolarFirstDate.year+Nyear) && (offset > 0);     i++) 
  494.     offset -= 365 + LeapYear(i);
  495.     if (offset<0)
  496.     {
  497.     --i;     /* LeapYear is a macro */
  498.     offset += 365 + LeapYear(i);
  499.     }
  500.     if (i==(SolarFirstDate.year + Nyear)) Error("Year out of range.");
  501.     d->year = i;
  502.     
  503.     /* assert(offset<(365+LeapYear(i))); */
  504.     for (m=1; m<=12; m++)
  505.     {
  506.     days = daysInSolarMonth[m];
  507.     if ((m==2) && LeapYear(i))    /* leap February */
  508.         days++;
  509.     if (offset<days)
  510.     {
  511.         d->month = m;
  512.         d->day = offset + 1;
  513.         return;
  514.     }
  515.     offset -= days;
  516.     }
  517. }
  518.  
  519.  
  520. int GZcycle(g, z)
  521. int g, z;
  522. {
  523.     int gz;
  524.  
  525.     for (gz = z; gz % 10 != g && gz < 60; gz += 12) ;
  526.     if (gz >= 60) printf("internal error\n");
  527.     return gz+1;
  528. }
  529.          
  530.  
  531. void CalGZ(offset, d, g, z)
  532. long offset;
  533. Date *d, *g, *z;
  534. {
  535.     int    year, month;
  536.         
  537.     year = d->year - LunarFirstDate.year;
  538.     month = year * 12 + d->month - 1;   /* leap months do not count */
  539.  
  540.     g->year = (GanFirstDate.year + year) % 10;
  541.     z->year = (ZhiFirstDate.year + year) % 12;
  542.     g->month = (GanFirstDate.month + month) % 10;
  543.     z->month = (ZhiFirstDate.month + month) % 12;
  544.     g->day = (GanFirstDate.day + offset) % 10;
  545.     z->day = (ZhiFirstDate.day + offset) % 12;
  546.     z->hour = ((d->hour + 1) / 2) % 12;
  547.     g->hour = (g->day * 12 + z->hour) % 10;
  548. }
  549.  
  550.  
  551. void Error(s)
  552. char    *s;
  553. {
  554.     printf("%s\n",s);
  555.     exit(1);
  556. }
  557.  
  558.  
  559. /* GetFest returns the jie day of the lunar i-th year, j-th month */
  560. int GetFest(i, j)
  561. int i, j;
  562. {
  563.     return(jie[j] + (fest[i] >> 2 * (11-j) & 0x3));
  564. }
  565.  
  566.  
  567. /* Compare two dates and return <,=,> 0 if the 1st is <,=,> the 2nd */
  568. int CmpDate(month1, day1, month2, day2)
  569. int month1, day1, month2, day2;
  570. {
  571.     if (month1!=month2) return(month1-month2);
  572.     if (day1!=day2) return(day1-day2);
  573.     return(0);
  574. }
  575.  
  576.  
  577. /*
  578.    Given a solar date, find the "lunar" date for the purpose of
  579.    calculating the "4-columns" by taking jie into consideration.
  580. */
  581. int JieDate(ds, dl)
  582. Date *ds, *dl;
  583. {
  584.     int m, flag;
  585.  
  586.     if (ds->month==1)
  587.     {
  588.     flag = CmpDate(ds->month, ds->day,
  589.                1, GetFest(ds->year - SolarFirstDate.year - 1, 11));
  590.     if (flag<0) dl->month = 11;
  591.     else if (flag>0) dl->month = 12;
  592.     dl->year = ds->year - 1;
  593.     return(flag==0);
  594.     }
  595.     for (m=2; m<=12; m++)
  596.     {
  597.     flag = CmpDate(ds->month, ds->day,
  598.                m, GetFest(ds->year - SolarFirstDate.year, m-2));
  599.     if (flag==0) m++;
  600.     if (flag<=0) break;
  601.     }
  602.     dl->month = (m-2) % 12;
  603.     dl->year = ds->year;
  604.     if ((dl->month)==0)
  605.     {
  606.     dl->year = ds->year - 1;
  607.     dl->month = 12;
  608.     }
  609.     return(flag==0);
  610. }
  611.  
  612.  
  613. /* Compute the number of days in each lunar year in the table */
  614. int make_yday()
  615. {
  616.     int year, i, leap;
  617.     long code;
  618.     
  619.     for (year = 0; year < Nyear; year++)
  620.     {
  621.     code = yearInfo[year];
  622.     leap = code & 0xf;
  623.     yday[year] = 0;
  624.     if (leap != 0)
  625.     {
  626.         i = (code >> 16) & 0x1;
  627.         yday[year] += moon[i];
  628.     }
  629.     code >>= 4;
  630.     for (i = 0; i < Nmonth-1; i++)
  631.     {
  632.         yday[year] += moon[code&0x1];
  633.         code >>= 1;
  634.     }
  635.     ymonth[year] = 12;
  636.     if (leap != 0) ymonth[year]++;
  637.     }
  638.     return Nyear;
  639. }
  640.  
  641.  
  642. /* Compute the days of each month in the given lunar year */
  643. int make_mday(year)
  644. int year;
  645. {
  646.     int i, leapMonth;
  647.     long code;
  648.     
  649.     code = yearInfo[year];
  650.     leapMonth = code & 0xf;
  651.     /* leapMonth == 0 means no leap month */
  652.     code >>= 4;
  653.     if (leapMonth == 0)
  654.     {
  655.     mday[Nmonth] = 0;
  656.     for (i = Nmonth-1; i >= 1; i--)
  657.     {
  658.         mday[i] = moon[code&0x1];
  659.         code >>= 1;
  660.     }
  661.     }
  662.     else
  663.     {
  664.     /* 
  665.       There is a leap month (run4 yue4) L in this year.
  666.       mday[1] contains the number of days in the 1-st month;
  667.       mday[L] contains the number of days in the L-th month;
  668.       mday[L+1] contains the number of days in the L-th leap month;
  669.       mday[L+2] contains the number of days in the L+1 month, etc.
  670.  
  671.       cf. yearInfo[]: info about the leap month is encoded differently.
  672.     */
  673.     i = (yearInfo[year] >> 16) & 0x1;
  674.     mday[leapMonth+1] = moon[i];
  675.     for (i = Nmonth; i >= 1; i--)
  676.     {
  677.         if (i == leapMonth+1) i--;
  678.         mday[i] = moon[code&0x1];
  679.         code >>= 1;
  680.     }
  681.     }
  682.     return leapMonth;
  683. }
  684.  
  685.  
  686. void Report()
  687. {
  688.     if (showHZ)
  689.     ReportGB();
  690.     else if (showBM)
  691.     ReportBM();
  692.     else
  693.     ReportE();
  694. }
  695.  
  696.  
  697. void ReportGB()
  698. {
  699.     printf("%s%d%s%2d%s%2d%s%2d%s%s%s\n", "ÑôÀú£ºªÁ",
  700.        solar.year, "Äê", solar.month, "ÔÂ", solar.day,
  701.        "ÈÕ", solar.hour, "ʱªÁ",
  702.        "ÐÇÆÚ", weekdayGB[solar.weekday]); 
  703.     printf("%s%d%s%s%2d%s%2d%s%s%s%s%s\n", "ÒõÀú£ºªÁ",
  704.        lunar.year, "Äê", (lunar.leap? "Èò":""),
  705.        lunar.month, "ÔÂ", lunar.day, "ÈÕ", 
  706.        ZhiGB[zhi.hour], "ʱªÁ",
  707.        "ÉúФÊô", ShengXiaoGB[zhi.year]);
  708.     printf("%s%s%s%s%s%s%s%s%s%s%s%s%s\n", "¸ÉÖ§£ºªÁ",
  709.        GanGB[gan.year], ZhiGB[zhi.year], "ÄêªÁ",
  710.        GanGB[gan.month], ZhiGB[zhi.month], "ÔªÁ",
  711.        GanGB[gan.day], ZhiGB[zhi.day], "ÈÕªÁ",
  712.        GanGB[gan.hour], ZhiGB[zhi.hour], "ʱªÁ");
  713.     printf("%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
  714.        "ÓÃËÄÖùÉñËãÍÆËã֮ʱ³½°Ë×Ö£ºªÁ",
  715.        GanGB[gan2.year], ZhiGB[zhi2.year], "ÄêªÁ",
  716.        GanGB[gan2.month], ZhiGB[zhi2.month], "ÔªÁ",
  717.        GanGB[gan2.day], ZhiGB[zhi2.day], "ÈÕªÁ",
  718.        GanGB[gan2.hour], ZhiGB[zhi2.hour], "ʱªÁ");
  719.     if (jieAlert)
  720.     {
  721.     printf("* %s, %s\n", "ÊÇÈÕΪ½Ú",
  722.            "ÔÂÖù¿ÉÄÜÒªÐÞ¸Ä");
  723.     if (lunar2.month==1)
  724.         printf("* %s\n", "ÄêÖùÒà¿ÉÄÜÒªÐÞ¸Ä");
  725.     printf("* %s\n", "Çë²éÓнÚÆøʱ¼äÖ®ÍòÄêÀú");
  726.     }
  727. }
  728.  
  729.  
  730. void ReportE()
  731. {
  732.     printf("Solar : %d.%d.%d.%d\t%s\n", solar.year, solar.month, solar.day,
  733.        solar.hour, weekday[solar.weekday]);
  734.     printf("Lunar : %d.%d%s.%d.%d\tShengXiao: %s\n",
  735.        lunar.year, lunar.month, (lunar.leap?"Leap":""), lunar.day,
  736.        lunar.hour, ShengXiao[zhi.year] );
  737.     printf("GanZhi: %s-%s.%s-%s.%s-%s.%s-%s\n",
  738.        Gan[gan.year], Zhi[zhi.year], Gan[gan.month], Zhi[zhi.month],
  739.        Gan[gan.day], Zhi[zhi.day], Gan[gan.hour], Zhi[zhi.hour]);
  740.     printf("        (GanZhi Order)\t%d-%d.%d-%d.%d-%d.%d-%d\n",
  741.        gan.year+1, zhi.year+1, gan.month+1, zhi.month+1,
  742.        gan.day+1, zhi.day+1, gan.hour+1, zhi.hour+1);
  743.     printf("        (JiaZi Cycle)\t%d.%d.%d.%d\n\n",
  744.        GZcycle(gan.year, zhi.year), GZcycle(gan.month, zhi.month),
  745.        GZcycle(gan.day, zhi.day), GZcycle(gan.hour, zhi.hour));
  746.     printf("BaZi (8-characters) according to 'Four Column Calculation':\n");
  747.     printf("        %s-%s.%s-%s.%s-%s.%s-%s\n",
  748.        Gan[gan2.year], Zhi[zhi2.year], Gan[gan2.month], Zhi[zhi2.month],
  749.        Gan[gan2.day], Zhi[zhi2.day], Gan[gan2.hour], Zhi[zhi2.hour]);
  750.     printf("        (GanZhi Order)\t%d-%d.%d-%d.%d-%d.%d-%d\n",
  751.        gan2.year+1, zhi2.year+1, gan2.month+1, zhi2.month+1,
  752.        gan2.day+1, zhi2.day+1, gan2.hour+1, zhi2.hour+1);
  753.     printf("        (JiaZi Cycle)\t%d.%d.%d.%d\n\n",
  754.        GZcycle(gan2.year, zhi2.year), GZcycle(gan2.month, zhi2.month),
  755.        GZcycle(gan2.day, zhi2.day), GZcycle(gan2.hour, zhi2.hour));
  756.     if (jieAlert)
  757.     {
  758.     printf("* The month column may need adjustment because the date falls on a jie.\n");
  759.     if (lunar2.month==1)
  760.         printf("* The day column may need adjustment, too.\n");
  761.     printf("* Please consult a detailed conversion table.\n");
  762.     }
  763. }
  764.  
  765.  
  766. void ReportBM()
  767. {
  768.     printf("Solar : %d.%d.%d.%d\t%s\n", solar.year, solar.month, solar.day,
  769.        solar.hour, weekday[solar.weekday]);
  770.     printf("Lunar : %d.%d%s.%d.%d\tShengXiao: %s\n",
  771.        lunar.year, lunar.month, (lunar.leap?"Leap":""), lunar.day,
  772.        lunar.hour, ShengXiao[zhi.year] );
  773.     printf("GanZhi: \n\n");
  774.     display3(gan.year+GanBM, zhi.year+ZhiBM, NianBM);
  775.     display3(gan.month+GanBM, zhi.month+ZhiBM, YueBM);
  776.     display3(gan.day+GanBM, zhi.day+ZhiBM, RiBM);
  777.     display3(gan.hour+GanBM, zhi.hour+ZhiBM, ShiBM);
  778.     printf("\nBaZi  : \n\n");
  779.     display3(gan2.year+GanBM, zhi2.year+ZhiBM, NianBM);
  780.     display3(gan2.month+GanBM, zhi2.month+ZhiBM, YueBM);
  781.     display3(gan2.day+GanBM, zhi2.day+ZhiBM, RiBM);
  782.     display3(gan2.hour+GanBM, zhi2.hour+ZhiBM, ShiBM);
  783.     if (jieAlert)
  784.     {
  785.     printf("* The month column may need adjustment because the date falls on a jie.\n");
  786.     if (lunar2.month==1)
  787.         printf("* The day column may need adjustment, too.\n");
  788.     printf("* Please consult a detailed conversion table.\n");
  789.     }
  790. }
  791.  
  792.  
  793. void readBM()
  794. {
  795.     int    i, j, k, m, c;
  796.     FILE *fp;
  797.  
  798.     if ((fp=fopen(BMfile,"r"))==NULL)
  799.     {
  800.     printf("Bitmap file '%s' not found.\n",BMfile);
  801.     exit(1);
  802.     }
  803.     for (i=0; i<NBM; i++)
  804.       for (j=0; j<BMRow; j++)
  805.       {
  806.       k = 0;
  807.       for (;;)
  808.       {
  809.           c = getc(fp);
  810.           if ((c==EOF) || (c=='\n')) break;
  811.           GZBM[i][j][k++] = c;
  812.       }
  813.       for (m=k; m<BMCol; m++) GZBM[i][j][m] = ' ';
  814.       }
  815.     fclose(fp);
  816. }
  817.  
  818.  
  819. /* Display three ganzhi characters in a row */
  820. void display3(i, j, k)
  821. int i,j,k;
  822. {
  823.     int    r,c;
  824.  
  825.     for (r=0; r<BMRow; r++)
  826.     {
  827.     for (c=0; c<BMCol; c++) putchar(GZBM[i][r][c]);
  828.     printf("  ");
  829.     for (c=0; c<BMCol; c++) putchar(GZBM[j][r][c]);
  830.     printf("    ");
  831.     for (c=0; c<BMCol; c++) putchar(GZBM[k][r][c]);
  832.     putchar('\n');
  833.     }
  834.     putchar('\n');
  835. }
  836.  
  837.  
  838.